console.log('array')

/*
	把一个数组分块成指定大小的小数组。
	使用 Array.from() 创建一个新的数组，它的长度就是生成 chunk(块) 的数量。
	使用 Array.slice() 将新数组的每个元素映射到长度为 size 的 chunk 中。
	如果原始数组不能均匀分割，最后的 chunk 将包含剩余的元素。
*/

const chunk1 = (arr, size) =>
	Array.from({
			length: Math.ceil(arr.length / size)
		}, (v, i) =>
		arr.slice(i * size, i * size + size)
	)

function chunk(arr, size) {
	return Array.from({
			length: Math.ceil(arr.length / size)
		},
		(v, i) => {
			return arr.slice(i * size, i * size + size)
		})
};

/*
	Array.from()第一个参数可以是，拥有length属性的对象，若干索引属性的对像，来创建一个新的数组对象
*/

chunk([1, 2, 3, 4, 5], 2)

/* ---------------------------------------------------------------------- */

/*
	从数组中移除 falsey 值的元素
	使用 Array.filter() 过滤掉数组中所有 假值元素(false, null, 0, "", undefined, 和 NaN)。
*/

const compact1 = arr => arr.filter(Boolean)

function compact(arr) {
	return arr.filter(Boolean)
};

compact([false, null, 0, '', undefined, NaN, 1])

/*
	Array.filter()第一个参数是一个 callback 例如 (value, index, array) => {console.log(value, index, array)}
	Boolean 是js 内置的函数 传入数据类型，然后返回 true false
*/

/* ---------------------------------------------------------------------- */

/*
	计算数组中值的出现次数。
	每次遇到数组中的某个特定值时，使用 Array.reduce() 来递增计数器。
*/

const countOccurrences1 = (arr, val) => arr.reduce((a, v) => (v === val ? a + 1 : a + 0), 0)

function countOccurrences(arr, val) {
	arr.reduce((accumulator, currentValue, currentIndex, list) => {
		return currentValue === val ? accumulator + 1 : accumulator + 0
	}, 0)
};

/*
	Array.reduce() 传入一个callback 和 initialValue
	initialValue 存在那么第一次循环 accumulator 就是 initialValue，如果没传就用第一个元素充当 accumulator
	callback会被执行length - 1 次，数组第一项不会被循环
	然后return 的值会传入下一次的 accumulator 中 currentValue currentIndex 是当前 的value index  list是array数组本身
*/

countOccurrences([1, 1, 2, 1, 2, 3], 1)

/* ---------------------------------------------------------------------- */

/*
	深度平铺一个数组。
	使用递归。 通过空数组([]) 使用 Array.concat() ，结合 展开运算符( ... ) 来平铺数组。 递归平铺每个数组元素。
*/

const deepFlatten1 = arr => [].concat(...arr.map(v => (Array.isArray(v) ? deepFlatten(v) : v)))

function deepFlatten(arr) {
	return [].concat(
		...arr.map(
			(v) => {
				return Array.isArray(v) ? deepFlatten(v) : v
			}
		)
	)
};

/*
	Array.concat() 可以传入多个参数
	...arr 结构后每个元素进行map循环 如果是数组就在此调用自己，如果不是数组就直接返回;
*/

deepFlatten([1, [2],
	[
		[3], 4
	], 5
])

/* ---------------------------------------------------------------------- */

/*
	返回两个数组之间的差异。
	根据数组 b 创建一个 Set 对象，然后在数组 a 上使用 Array.filter() 方法，过滤出数组 b 中不包含的值。
*/

const difference1 = (a, b) => {
	const s = new Set(b)
	return a.filter(x => !s.has(x))
}

function difference(a, b) {
	const s = new Set(b)
	return a.filter(
		(item) => {
			return !s.has(item)
		}
	)
};

/*
	Set 是类似于数组的一种结构，它类似于数组，但是成员的值都是唯一的，没有重复的值。
	Set.has() 可以判断传入参数 在Set中是否存在
*/

difference([1, 2, 3], [1, 2, 4])

/* ---------------------------------------------------------------------- */

/*
	将数组中任意元素移动到任意位置,不影响原有数组
*/

function changeArrayIndex(arr, findData, to, ruleFn) {
	let rule = ruleFn || function defaultRule(findData, item) {
		return findData === item
	}

	let newArr = arr.filter((item, index, array) => {
		if (rule(findData, item)) {
			return false
		}
		return item
	})
	newArr.splice(to, 0, findData)
	return newArr
}

// ******************************  分割  ***************************************

/**
 * difArray 比较2个数组，返回各自数组独有的对象和公共的对象
 * @param  {String}   key  依据key代表的字段进行比较
 * @param  {Array}   arr1 进行对比的数组
 * @param  {Array}   arr2 进行对比的数组
 * @return {JSON}      返回一个JSON其中包含2个数组各自的独有对象和2个数组的
 */
function difArray(key, arr1, arr2) {
	if (!(typeof key === 'string') || !Array.isArray(arr1) || !Array.isArray(arr2)) {
		return {}
	}
	let array = arr2.concat(arr1)
	// 共有对象
	let allOnly = new Set()
	let common = new Set()
	let arr1CommonArr = []
	let arr2CommonArr = []
	let arr1OnlyArr = []
	let arr2OnlyArr = []
	array.forEach((item, index, arr) => {
		if (allOnly.has(item[key])) {
			common.add(item[key])
		} else {
			allOnly.add(item[key])
		}
	})
	arr1.forEach((item, index, arr) => {
		if (common.has(item[key])) {
			arr1CommonArr.push(item)
		} else {
			arr1OnlyArr.push(item)
		}
	})
	arr2.forEach((item, index, arr) => {
		if (common.has(item[key])) {
			arr2CommonArr.push(item)
		} else {
			arr2OnlyArr.push(item)
		}
	})
	return {
		arr1CommonArr,
		arr2CommonArr,
		arr1OnlyArr,
		arr2OnlyArr
	}
}
